﻿using System;
using System.Windows;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Tasks;

namespace Phoenix.Tasks
{
    public class PhoneTaskManager : ITaskManager
    {
        public void StartTask<TChooser, TTaskEventArgs>(Action<TTaskEventArgs> onComplete)
            where TChooser : ChooserBase<TTaskEventArgs>, new()
            where TTaskEventArgs : TaskEventArgs
        {
            var chooser = new TChooser();
            chooser.Completed += (x, y) => onComplete(y);
            chooser.Show();
        }

        /// <summary>
        /// Opens the Email Compose Task
        /// </summary>
        /// <param name="to"></param>
        /// <param name="cc"></param>
        /// <param name="bcc">Not supported by v7.0 (does nothing)</param>
        /// <param name="subject"></param>
        /// <param name="body"></param>
        /// <param name="codePage">Not supported by v7.0 (does nothing)</param>
        public void ComposeEmail(
            string to = null,
            string cc = null,
            string bcc = null,
            string subject = null,
            string body = null,
            int? codePage = null)
        {
            new EmailComposeTask
            {
                To = to,
                Cc = cc,
                Subject = subject,
                Body = body,
                Bcc = bcc,
                CodePage = codePage,
            }.Show();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="uri"></param>
        public void ShowWebsiteInBrowser(string uri)
        {
            new WebBrowserTask
            {
                Uri = new Uri(uri, UriKind.Absolute)
            }.Show();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="showAppBar">Should we show the app bar with the option to launch in IE</param>
        /// <param name="navigateCallback">Callback if you want to know when the web browser control navigates</param>
        /// <param name="loadCompleteCallback">Callback if you want to know when the web browser finishes loading content</param>
        public void ShowWebsiteInApp(string uri, bool showAppBar = true, 
            Action<NavigationEventArgs, NavigationService> navigateCallback = null,
            Action<NavigationEventArgs, string, NavigationService> loadCompleteCallback = null)
        {
            var uriString = string.Format("/Phoenix;component/WebPageView.xaml?Page={0}&ShowAppBar={1}", uri, showAppBar);
            var phoneApplicationFrame = (PhoneApplicationFrame)Application.Current.RootVisual;
            var phoneApplicationPage = ((PhoneApplicationPage)phoneApplicationFrame.Content);

            if (navigateCallback != null)
            {
                NavigatedEventHandler navigationServiceOnNavigated = null;
                navigationServiceOnNavigated = (sender, e) =>
                                                   {
                                                       var webPageView = ((WebPageView) e.Content);
                                                       //When we navigate to WebPageView, unregister from navigated event
                                                       phoneApplicationPage.NavigationService.Navigated -= navigationServiceOnNavigated;
                                                       
                                                       //Wire up browser navigated event to callback to invoker
                                                       EventHandler<NavigationEventArgs> browserOnNavigated =
                                                           (navSender, navE) =>
                                                           {
                                                               if (navigateCallback != null)
                                                                   navigateCallback(navE, phoneApplicationPage.NavigationService);
                                                           };
                                                       LoadCompletedEventHandler loadCompleted = 
                                                           (o, args) =>
                                                           {
                                                               webPageView.progress.IsLoading = false;
                                                               webPageView.progress.Visibility = Visibility.Collapsed;
                                                               if (loadCompleteCallback != null)
                                                                   loadCompleteCallback(args, webPageView.browser.SaveToString(), phoneApplicationPage.NavigationService);
                                                           };
                                                       EventHandler<NavigatingEventArgs> navigating =
                                                           (o, args) =>
                                                           {
                                                               webPageView.progress.IsLoading = true;
                                                               webPageView.progress.Visibility = Visibility.Visible;
                                                           };

                                                       webPageView.browser.Navigating += navigating;
                                                       webPageView.browser.Navigated += browserOnNavigated;
                                                       webPageView.browser.LoadCompleted += loadCompleted;
                                                       //Wire up navigated event for navigating away (to IE, or back to invoker)
                                                       // and unwire all events so we don't leak
                                                       NavigatedEventHandler cleanupHandler = null;
                                                       cleanupHandler = (cleanupSender, cleanupArgs) =>
                                                                            {
                                                                                webPageView.browser.Navigating -= navigating;
                                                                                webPageView.browser.Navigated -= browserOnNavigated;
                                                                                webPageView.browser.LoadCompleted -= loadCompleted;
                                                                                phoneApplicationPage.NavigationService.Navigated -= cleanupHandler;
                                                                            };
                                                       phoneApplicationPage.NavigationService.Navigated += cleanupHandler;
                                                   };

                phoneApplicationPage.NavigationService.Navigated += navigationServiceOnNavigated;
            }

            phoneApplicationPage.NavigationService.Navigate(new Uri(uriString, UriKind.Relative));
        }
    }
}
